package register

import (
	"bytes"
	"encoding/json"
	"fmt"
	logger "gitee.com/zaper/private-logger"
	"gitee.com/zaper/service-center-client/service/discover"
	"gitee.com/zaper/service-center-client/service/service_info"
	"gitee.com/zaper/service-config-client/os_env"
	"gitee.com/zaper/service-config-client/util"
	fmkconst "gitee.com/zaper/software-framework/constant"
	fmkutil "gitee.com/zaper/software-framework/util"
	"os"
	"sync"
)

const (
	registerInterface = "/api/v1/config/register"
)

var (
	registerClientManagerOnce   sync.Once
	registerClientManagerSingle *ConfigRegisterManager
)

type ConfigRegisterManager struct {
	httpClient *fmkutil.HttpClientManager
	service    *ServiceModel
}

func GetConfigRegisterManager() *ConfigRegisterManager {
	registerClientManagerOnce.Do(func() {
		registerClientManagerSingle = &ConfigRegisterManager{
			httpClient: fmkutil.NewHttpClientManager(),
		}
	})
	return registerClientManagerSingle
}

func (registerClientManager *ConfigRegisterManager) register() (string, bool) {
	logger.Infof("[service-config] Start register config service")
	var service = &ServiceModel{}
	service.ServiceId = os.Getenv(os_env.ServiceIdKey)
	registerClientManager.service = service
	request, err := json.Marshal(service)
	if err != nil {
		return "", false
	}
	instance := GetConfigServiceInstance()
	if instance == nil {
		return "", false
	}
	registerUrl := fmt.Sprintf("%s%s%s",
		"https://", instance.Endpoints[0], registerInterface)
	resp, err := registerClientManager.httpClient.Post(registerUrl, fmkconst.ContentType, bytes.NewReader(request))
	if err != nil {
		return "", false
	}
	return parseRegisterResult(resp)
}

func (registerClientManager *ConfigRegisterManager) keepAlive(leaseID string) (string, bool) {
	logger.Infof("[service-config] Config service keep, serviceName is %s, leaseId %s", registerClientManager.service.ServiceId,
		leaseID)
	registerClientManager.service.LeaseId = leaseID
	request, err := json.Marshal(registerClientManager.service)
	if err != nil {
		return "", false
	}
	instance := GetConfigServiceInstance()
	if instance == nil {
		return "", false
	}
	registerUrl := fmt.Sprintf("%s%s%s",
		"https://", instance.Endpoints[0], registerInterface)
	resp, err := registerClientManager.httpClient.Post(registerUrl, fmkconst.ContentType, bytes.NewReader(request))
	if err != nil {
		return "", false
	}
	return parseRegisterResult(resp)
}

func parseRegisterResult(r []byte) (string, bool) {
	response := &util.HttpResponseError{}
	err := json.Unmarshal(r, response)
	if err != nil {
		return "", false
	}
	if response.ErrorCode == 0 {
		leaseID := response.ErrorMess.(map[string]interface{})["LeaseID"].(string)
		return leaseID, true
	}
	return "", false
}

func GetConfigServiceInstance() *service_info.InstanceInfo {
	center := discover.GetDiscoverClientManager()
	instances := center.GetServiceInfo("service-config")
	var instance *service_info.InstanceInfo
	if len(instances) >= 1 {
		instance = &instances[0]
	}
	return instance
}
